﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using Common;
using AutoFacUtils;
using CashFlow.Db.DAL;
using CashFlow.Db.Entity;
using CashFlow.Db.IRepository;
using SysTool._00_Def;

namespace SysTool._02_Service
{
    public class UserService
    {
        private static IUserInfoRepository GetUserInfoRepository() { return AutoFacHelper.Get<IUserInfoRepository>(); }
        private static IShopRepository GetShopRepository() { return AutoFacHelper.Get<IShopRepository>(); }

        public static UserInfoEntity LoginUserInfo { get; private set; }
        public static ShopInfoEntity ShopInfo { get; private set; }

        public static EUserLoginResult Login(string phone, string pwd)
        {
            EUserLoginResult result = EUserLoginResult.Fail;

            string pwd2 = Md5EncryptionTool.Encrypt(pwd, true);
            var repos = GetUserInfoRepository();
            var ui = repos.QuerySingle(x => x.Password == pwd2 && x.Phone == phone);
            if (ui != null)
            {
                var shopRepos = GetShopRepository();
                var si = shopRepos.QuerySingle(x => x.ShopManagerUserId == ui.Id);
                if (si != null)
                {
                    LoginUserInfo = ui;
                    ShopInfo = si;
                    result = EUserLoginResult.Success;
                }
                else
                {
                    //result = EUserLoginResult.NotShopManager;
                }
            }
            else
            {
                result = EUserLoginResult.InvalidPwd;
            }

            return result;
        }

        public static UserInfoAndReferenceUserInfo QueryByUserId(int userId)
        {
            using (var db = SqlSugarHelper.GetDb())
            {
                return db.Queryable<UserInfoEntity>()
                    .LeftJoin<UserInfoEntity>((u1, u2) => u1.ReferenceInvitationCode == u2.InvitationCode)
                    .Where((u1, u2) => u1.Id == userId)
                    .Select((u1, u2) => new UserInfoAndReferenceUserInfo
                    {
                        UserInfo = u1,
                        ReferenceUserInfo = u2
                    })
                    .First();
            }
        }

        public static bool ResetPwd(UserInfoEntity userInfo)
        {
            using (var db = SqlSugarHelper.GetDb())
            {
                int n = db.Updateable(userInfo).ExecuteCommand();
                return n > 0;
            }
        }

        public static bool UpdateUser(UserInfoEntity userInfo)
        {
            using (var db = SqlSugarHelper.GetDb())
            {
                int n2 = db.Queryable<UserInfoEntity>()
                    .Where(x => x.Id != userInfo.Id && x.Phone == userInfo.Phone)
                    .Count();
                if (n2 == 0)
                {
                    int n = db.Updateable(userInfo).ExecuteCommand();
                    return n > 0;
                }
                else
                {
                    return false;
                }
            }
        }

        public static IList<UserInfoEntity> QueryAllUsersByUserId(int userId)
        {
            IList<UserInfoEntity> ls = new List<UserInfoEntity>();

            using (var db = SqlSugarHelper.GetDb())
            {
                var entity = db.Queryable<UserInfoEntity>().Where(x => x.Id == userId).First();
                if (entity != null)
                {
                    ls.Add(entity);

                    Queue<string> queue = new Queue<string>();
                    string referenceInvitationCode = entity.InvitationCode;

                    var ls2 = db.Queryable<UserInfoEntity>().Where(x => x.ReferenceInvitationCode == referenceInvitationCode).ToList();
                    foreach (var item in ls2)
                    {
                        ls.Add(item);
                        queue.Enqueue(item.InvitationCode);
                    }

                    while (queue.Count > 0)
                    {
                        string referenceInvitationCode2 = queue.Dequeue();
                        var ls3 = db.Queryable<UserInfoEntity>().Where(x => x.ReferenceInvitationCode == referenceInvitationCode2).ToList();
                        foreach (var item in ls3)
                        {
                            ls.Add(item);
                            queue.Enqueue(item.InvitationCode);
                        }
                    }
                }
            }

            return ls;
        }

        public static IList<UserInfoAndReferenceUserInfo> QueryAllUsersWithSameShopByUserId(int userId)
        {
            IList<UserInfoAndReferenceUserInfo> ls = new List<UserInfoAndReferenceUserInfo>();

            var shopInfo = ShopService.QueryShopInfoByUserId(userId);
            using (var db = SqlSugarHelper.GetDb())
            {
                var entity = db.Queryable<UserInfoEntity>()
                    .LeftJoin<UserInfoEntity>((u, ru) => u.ReferenceInvitationCode == ru.InvitationCode)
                    .Where((u, ru) => u.Id == userId)
                    .Select((u, ru) => new UserInfoAndReferenceUserInfo
                    {
                        UserInfo = u,
                        ReferenceUserInfo = ru
                    })
                    .First();
                if (entity != null)
                {
                    ls.Add(entity);

                    Queue<string> queue = new Queue<string>();
                    string referenceInvitationCode = entity.UserInfo.InvitationCode;

                    var ls2 = db.Queryable<UserInfoEntity>()
                        .InnerJoin<ShopUserEntity>((u, s) => u.Id == s.UserId && s.ShopManagerUserId == shopInfo.ShopManagerUserId)
                        .LeftJoin<UserInfoEntity>((u, s, ru) => u.ReferenceInvitationCode == ru.InvitationCode)
                        .Where((u, s, ru) => u.ReferenceInvitationCode == referenceInvitationCode)
                        .Select((u, s, ru) => new UserInfoAndReferenceUserInfo
                        {
                            UserInfo = u,
                            ReferenceUserInfo = ru
                        })
                        .ToList();
                    foreach (var item in ls2)
                    {
                        ls.Add(item);
                        queue.Enqueue(item.UserInfo.InvitationCode);
                    }

                    while (queue.Count > 0)
                    {
                        string referenceInvitationCode2 = queue.Dequeue();
                        var ls3 = db.Queryable<UserInfoEntity>()
                            .InnerJoin<ShopUserEntity>((u, s) => u.Id == s.UserId && s.ShopManagerUserId == shopInfo.ShopManagerUserId)
                            .LeftJoin<UserInfoEntity>((u, s, ru) => u.ReferenceInvitationCode == ru.InvitationCode)
                            .Where((u, s, ru) => u.ReferenceInvitationCode == referenceInvitationCode2)
                            .Select((u, s, ru) => new UserInfoAndReferenceUserInfo
                            {
                                UserInfo = u,
                                ReferenceUserInfo = ru
                            })
                            .ToList();
                        foreach (var item in ls3)
                        {
                            ls.Add(item);
                            queue.Enqueue(item.UserInfo.InvitationCode);
                        }
                    }
                }
            }

            return ls;
        }

        public static IList<UserInfoAndReferenceUserInfo> QueryAllUsers()
        {
            using (var db = SqlSugarHelper.GetDb())
            {
                var ls = db.Queryable<UserInfoEntity>()
                    .InnerJoin<UserInfoEntity>((u1, u2) => u1.ReferenceInvitationCode == u2.InvitationCode)
                    .Select((u1, u2) => new UserInfoAndReferenceUserInfo
                    {
                        UserInfo = u1,
                        ReferenceUserInfo = u2
                    })
                    .ToList();
                return ls;
            }
        }
    }
}
